123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- <!-- @format -->
- <script lang="ts" setup>
- import { ArrowRight } from '@element-plus/icons-vue'
- import { Swiper, SwiperSlide } from 'swiper/vue'
- import { Navigation, Pagination } from 'swiper/modules'
- import dayjs from 'dayjs'
- import { ConstKeys } from '~/enums/const-enums'
- import { PageSizeEnum } from '~/enums/sizeEnum'
- import {
- getFeatureAlumDetailApi,
- getFeatureBrandsListApi,
- getFeatureDetailApi,
- getFeatureGoodsListApi,
- } from '~/api/model/feature'
- import img02 from '~/assets/images/featured_img02.png'
- import img03 from '~/assets/images/featured_img03.png'
- import img04 from '~/assets/images/featured_img04.png'
- import img05 from '~/assets/images/featured_img05.png'
- import 'swiper/css'
- import 'swiper/css/navigation'
- // import "swiper/css/pagination"
- import { useUserStore } from '@/stores/modules/user'
- enum Type {
- Detail = '0',
- Album = '1',
- }
- const userStore = useUserStore()
- const { isLogin } = storeToRefs(userStore)
- const { openLoginModal } = useLoginModal()
- const modules = [Navigation, Pagination]
- const brandList = ref<any>([])
- const swiperVertical = ref<any>(null)
- const detail = ref()
- const list = ref<any>([])
- const currentPage = ref(0)
- const total = ref(0)
- const page_size = ref(20)
- const isEffective = ref(true)
- const staticList = ref([
- {
- icon: img02,
- title: 'Source Manufacturers',
- subTitle:
- 'Selected product suppliers with the capability to develop unique products.',
- },
- {
- icon: img03,
- title: 'Competitive Pricing',
- subTitle:
- 'Get the best quality products at the most competitive wholesale prices.',
- },
- {
- icon: img04,
- title: 'Strict Quality Control',
- subTitle:
- 'Strict quality inspection to ensure the products meet our high standards.',
- },
- {
- icon: img05,
- title: 'Dedicated Support',
- subTitle:
- 'Smooth wholesale experience with dedicated customer manager service.',
- },
- ])
- const route = useRoute()
- const paintingId = route.query.paintingId
- const slug = route.params.name
- const { data, pending, error, refresh } = await useAsyncData(
- 'featured-detail',
- () => $fetch(`${ConstKeys.DOMAINPRO}/client/topic/detail`, { params: { slug } }),
- )
- const seoData = data.value?.result
- useHead({
- title: seoData?.title,
- meta: [
- {
- name: 'description',
- content: seoData?.headImageText,
- },
- {
- property: 'og:title',
- content: seoData?.title,
- },
- {
- property: 'og:description',
- content: seoData?.headImageText,
- },
- {
- property: 'og:type',
- content: 'website',
- },
- {
- property: 'twitter:title',
- content: seoData?.title,
- },
- {
- property: 'twitter:description',
- content: seoData?.headImageText,
- },
- {
- property: 'twitter:card',
- content: 'summary_large_image',
- },
- ],
- link: [
- {
- rel: 'canonical',
- href: `${ConstKeys.DOMAINPRO}/collections/${slug}`,
- },
- ],
- })
- const isType = computed(() => detail.value?.type === Type.Detail)
- async function getFeatureDetail() {
- try {
- const result = await getFeatureDetailApi({ slug })
- detail.value = result
- }
- catch (error) {
- console.log('error', error)
- }
- }
- async function getFeatureAlumDetail() {
- try {
- const result = await getFeatureAlumDetailApi({ paintingId })
- isEffective.value = true
- detail.value = result
- }
- catch (error: any) {
- if (error.code === 10010)
- isEffective.value = false
- console.log('error', error)
- }
- }
- async function getFeatureProductList(
- pageNo = PageSizeEnum.PAGE,
- pageSize = page_size.value,
- ) {
- const res: any = await getFeatureGoodsListApi({
- pageNo,
- pageSize,
- topicSlug: slug,
- })
- list.value = res.records
- currentPage.value = res.current
- total.value = res.total
- }
- function updatePage(currentPage: number, pageSize: number) {
- getFeatureProductList(currentPage, pageSize)
- }
- async function getHomeBrandList() {
- try {
- const data: any = await getFeatureBrandsListApi({
- pageNo: 1,
- pageSize: page_size.value,
- topicSlug: slug,
- })
- brandList.value = data.records
- }
- catch (error) {
- console.log('error', error)
- }
- }
- function onVerticalSwiper(swiper: any) {
- swiperVertical.value = swiper
- }
- function onClickLeft() {
- swiperVertical.value.slidePrev()
- }
- function onClickRight() {
- swiperVertical.value.slideNext()
- }
- function getData() {
- if (!paintingId) {
- getHomeBrandList()
- getFeatureProductList()
- getFeatureDetail()
- }
- else {
- getFeatureAlumDetail()
- }
- }
- getData()
- async function openLogin() {
- await openLoginModal()
- }
- </script>
- <template>
- <div class="pos-relative">
- <div v-if="isType" class="fixed-image">
- <img
- :src="detail?.headImageUrl"
- class="w-full h-360px object-cover"
- alt=""
- srcset=""
- >
- </div>
- <div class="scrollable-content">
- <div
- v-if="isType"
- :class="isType ? 'h-360px' : ''"
- class="content-header"
- >
- <h1 class="!text-36px !fw-700 custom-title-font">
- {{ detail?.title }}
- </h1>
- <div class="text-18px">
- {{ detail?.headImageText }}
- </div>
- </div>
- <div :class="isType ? 'bg-#fff' : ''">
- <div v-if="isEffective" class="w-1400px mx-auto pt-40px pb-60px">
- <el-breadcrumb :separator-icon="ArrowRight">
- <el-breadcrumb-item :to="{ path: '/' }">
- Home
- </el-breadcrumb-item>
- <el-breadcrumb-item :to="{ path: '/collections' }">
- Collections
- </el-breadcrumb-item>
- <el-breadcrumb-item> {{ detail?.title }}</el-breadcrumb-item>
- </el-breadcrumb>
- </div>
- <div v-if="isEffective" class="w-1400px mx-auto mb-60px">
- <h1 class="!text-26px !fw-700 text-#363C40 custom-title-font">
- {{ detail?.title }}
- </h1>
- <div class="flex my-24px text-#7C7C7C text-18px">
- <div class="mr-48px">
- {{ dayjs(detail?.createTime).format('MMMM D, YYYY') }}
- </div>
- <div v-if="isType">
- {{ detail?.merchandiseQuantity }} products
- </div>
- </div>
- <div
- class="text-18px lh-24px line-clamp-3 text-#666"
- :title="detail?.headImageText"
- >
- {{ detail?.headImageText }}
- </div>
- </div>
- <div>
- <div v-if="isType">
- <div
- v-if="isLogin || !detail?.userEnable"
- class="w-1400px mx-auto pb-160px"
- >
- <div
- v-if="list.length"
- class="grid grid-gap-x-65px grid-gap-y-80px grid-cols-4"
- >
- <div v-for="item in list" :key="item.id">
- <common-goods-item :item />
- </div>
- </div>
- <common-empty v-else class="py-50px" title="">
- <template #icon>
- <img
- src="~/assets/images/featured_empty.png"
- class="w-200px h-200px"
- alt=""
- srcset=""
- >
- </template>
- </common-empty>
- <div v-if="list.length" class="mt-60px flex justify-center">
- <el-pagination
- v-model:current-page="currentPage"
- :page-size="page_size"
- :pager-count="10"
- layout="prev, pager, next"
- :total="total"
- @change="updatePage"
- />
- </div>
- </div>
- <div
- v-else
- class="w-1400px mx-auto pt-80px pb-160px flex justify-center"
- >
- <div class="cursor-pointer" @click="openLogin">
- <svgo-lock class="!w-100px !h-100px text-#999 m-auto" />
- <div class="text-#999 text-42px mt-20px">
- Login to view
- </div>
- </div>
- </div>
- </div>
- <div v-else class="text-#000 w-1400px mx-auto pb-160px">
- <div
- v-if="isEffective"
- class="text-#333333 content-detail custom-html"
- v-html="detail?.content"
- />
- <div v-else class="pt-160px">
- Sorry, the shared content has expired.
- </div>
- </div>
- <div
- v-if="isType"
- class="flex justify-center items-center py-82px bg-#FAF5F1"
- >
- <div class="w-600px">
- <h2 class="fw-700 text-32px text-#333 !mb-60px">
- Quality Wholesale, Inspiring Global Retail
- </h2>
- <div
- v-for="(item, index) in staticList"
- :key="index"
- class="flex items-center mb-40px last:mb-0"
- >
- <img :src="item.icon" alt="" srcset="" class="w-40px h-40px">
- <div class="ml-30px w-430px">
- <h3 class="!fw-500 text-26px text-#333 lh-30px">
- {{ item.title }}
- </h3>
- <div class="mt-10px text-18px text-#999 lh-28px">
- {{ item.subTitle }}
- </div>
- </div>
- </div>
- </div>
- <img
- src="~/assets/images/featured_img01.png"
- class="w-566px h-480px object-cover ml-10px"
- alt=""
- srcset=""
- >
- </div>
- <div v-if="isType" class="py-160px w-1400px mx-auto">
- <h2 class="!mb-40px fw-700 text-40px text-#363C40">
- Collection Brands
- </h2>
- <div v-if="brandList.length">
- <div class="w-1300px mx-auto pos-relative">
- <div
- class="pos-absolute cursor-pointer left--46px top-200px w-28px h-28px transform-translate-y--50% cursor-not-allowed !cursor-pointer flex justify-center items-center"
- @click="onClickLeft()"
- >
- <img
- src="~/assets/images/arrow_left.png"
- alt=""
- class="w-26px h-26px"
- srcset=""
- >
- </div>
- <div
- class="pos-absolute cursor-pointer right--46px top-200px w-28px h-28px transform-translate-y--50% cursor-not-allowed !cursor-pointer flex justify-center items-center"
- @click="onClickRight()"
- >
- <img
- src="~/assets/images/arrow_right.png"
- alt=""
- class="w-26px h-26px"
- srcset=""
- >
- </div>
- <Swiper
- :slides-per-view="4"
- :space-between="55"
- :modules="modules"
- :loop="true"
- :navigation="false"
- :pagination="true"
- class="pos-relative"
- @swiper="onVerticalSwiper"
- >
- <SwiperSlide v-for="(item, index) in brandList" :key="index">
- <common-brand-item :item="item" />
- </SwiperSlide>
- </Swiper>
- </div>
- </div>
- <common-empty v-else class="pt-50px" title="">
- <template #icon>
- <img
- src="~/assets/images/featured_empty.png"
- class="w-200px h-200px"
- alt=""
- srcset=""
- >
- </template>
- </common-empty>
- </div>
- </div>
- </div>
- <AppFooter class="bg-#fff" />
- </div>
- </div>
- </template>
- <style lang="less" scoped>
- .fixed-image {
- position: fixed;
- top: 151px;
- left: 0;
- width: 100%;
- height: 360px;
- z-index: 1;
- overflow: hidden;
- }
- .scrollable-content {
- position: relative;
- z-index: 2;
- width: 100%;
- color: white;
- .content-header {
- display: flex;
- // height: 360px;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- text-align: center;
- background: rgba(0, 0, 0, 0.4);
- /* 半透明背景使文字在图片上更可读 */
- }
- ::v-deep(.content-detail) {
- font-family: sans-serif;
- h2 {
- font-size: 1.5em;
- font-family: 'CustomTitleFont';
- margin-top: 1em !important;
- margin-bottom: 1em !important;
- font-weight: bold;
- }
- h3 {
- display: block;
- font-size: 1.17em;
- margin-block-start: 1em;
- margin-block-end: 1em;
- margin-inline-start: 0px;
- margin-inline-end: 0px;
- margin-bottom: 1em !important;
- font-weight: bold;
- unicode-bidi: isolate;
- font-family: 'CustomTitleFont';
- }
- p {
- display: block;
- margin-block-start: 1em;
- margin-block-end: 1em;
- margin-inline-start: 0px;
- margin-inline-end: 0px;
- unicode-bidi: isolate;
- }
- ul {
- display: block;
- list-style-type: disc;
- margin-block-start: 1em;
- margin-block-end: 1em;
- margin-inline-start: 0px;
- margin-inline-end: 0px;
- padding-inline-start: 40px;
- unicode-bidi: isolate;
- li {
- display: list-item;
- text-align: -webkit-match-parent;
- unicode-bidi: isolate;
- }
- }
- ol {
- list-style-type: decimal;
- display: block;
- list-style-type: decimal;
- margin-block-start: 1em;
- margin-block-end: 1em;
- margin-inline-start: 0px;
- margin-inline-end: 0px;
- padding-inline-start: 40px;
- unicode-bidi: isolate;
- }
- }
- }
- </style>
|